package com.taobao.hsf.guide.iolistener;

import com.taobao.hsf.annotation.Order;
import com.taobao.hsf.annotation.Scope;
import com.taobao.hsf.annotation.Tag;
import com.taobao.hsf.io.RequestPacket;
import com.taobao.hsf.io.ResponsePacket;
import com.taobao.hsf.io.common.ThreadLocalCache;
import com.taobao.hsf.io.remoting.hsf.message.HSFRequestPacket;
import com.taobao.hsf.io.remoting.hsf.message.HSFResponsePacket;
import com.taobao.hsf.io.server.Server;
import com.taobao.hsf.io.stream.ServerStream;
import com.taobao.hsf.io.stream.support.ServerStreamMessageListenerAdapter;
import com.taobao.hsf.logger.LoggerInit;
import com.taobao.middleware.logger.Logger;

import org.apache.commons.lang.StringUtils;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author weipeng2k 2017年10月26日 下午15:54:21
 */
@Tag({"tcp", "http"})
@Scope(Scope.Option.SINGLETON)
@Order(1000)
public class ServerLogStreamMessageListener extends ServerStreamMessageListenerAdapter {

    private static final ConcurrentHashMap<Long, Boolean> relationMap = new ConcurrentHashMap<Long, Boolean>();
    private static Logger logger = LoggerInit.LOGGER;
    private static String serviceName = System.getProperty("hsf.log.service.name");
    private static String methodName = System.getProperty("hsf.log.method.name");

    @Override
    public void write(Server server, ServerStream stream, ResponsePacket message) {
        if (message instanceof HSFResponsePacket) {
            HSFResponsePacket responsePacket = (HSFResponsePacket) message;

            if (relationMap.get(message.requestId()) == Boolean.TRUE) {
                logger.info(
                        "ServerLogStreamMessageListener#write\nresponse: id=" + responsePacket.requestId() + ", status=" + responsePacket.status() + " to " + stream.remoteIp());
            }
        }
    }

    @Override
    public void writeSuccess(Server server, ServerStream stream, ResponsePacket message) {
        if (message instanceof HSFResponsePacket) {
            HSFResponsePacket responsePacket = (HSFResponsePacket) message;

            if (relationMap.remove(message.requestId()) == Boolean.TRUE) {
                logger.info(
                        "ServerLogStreamMessageListener#writeSuccess\nresponse: id=" + responsePacket.requestId() + ", status=" + responsePacket.status() + " to " + stream.remoteIp());
            }
        }
    }

    @Override
    public void writeFailed(Server server, ServerStream stream, ResponsePacket message, Throwable cause) {
        if (message instanceof HSFResponsePacket) {
            HSFResponsePacket responsePacket = (HSFResponsePacket) message;

            if (relationMap.remove(message.requestId()) == Boolean.TRUE) {
                logger.info(
                        "ServerLogStreamMessageListener#writeFailed\nresponse: id=" + responsePacket.requestId() + ", status=" + responsePacket.status() + " to " + stream.remoteIp());
            }
        }
    }

    @Override
    public void received(Server server, ServerStream stream, RequestPacket message) {
        if (message instanceof HSFRequestPacket) {
            HSFRequestPacket requestPacket = (HSFRequestPacket) message;

            String serviceUniqueName = requestPacket.serviceUniqueName();

            if (serviceName != null && StringUtils.equals(serviceUniqueName, serviceName)) {
                String targetMethod = ThreadLocalCache.getString(requestPacket.getTargetMethod());
                if (methodName != null && StringUtils.equals(targetMethod, methodName)) {
                    relationMap.put(requestPacket.requestId(), Boolean.TRUE);
                    logger.info(
                            "ServerLogStreamMessageListener#received\nrequest: id=" + requestPacket.requestId() + " " + requestPacket + " from " + stream.remoteIp());
                } else {
                    relationMap.put(requestPacket.requestId(), Boolean.TRUE);
                    logger.info(
                            "ServerLogStreamMessageListener#received\nrequest: id=" + requestPacket.requestId() + " " + requestPacket + " from " + stream.remoteIp());
                }
            }
        }
    }
}
